# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html

#from scrapy.pipelines.images import ImagesPipeline
from scrapy.exporters import JsonItemExporter #scrapy提供的json处理类
from twisted.enterprise import adbapi #将mysql的操作变成异步操作
import MySQLdb
import MySQLdb.cursors
import codecs #可以避免open类一样的编码问题
import json
class ArticlespiderPipeline(object):
    def process_item(self, item, spider):
        return item

#自定义json处理类将数据写入到json文件
class JsonWithEncodingPipeline(object):
    def __init__(self):
        self.file=codecs.open("article.json","w",encoding="utf-8")
    def process_item(self,item,spider):
        lines=json.dumps(dict(item),ensure_ascii=False) + "\n" #ensure_ascii=False防止中文乱码，dumps方法用于将字典转换成str
        self.file.write(lines)
        return item
    def spider_closed(self,spider):
        self.file.close()

#调用scrapy提供的json处理类
class JsonExproterPipleling(object):
    def __init__(self):
        self.file=open('article_export.json','wb')
        self.exporter = JsonItemExporter(self.file,encoding="utf-8",ensure_ascii=False)#设置参数
        self.exporter.start_exporting()#开始处理
    def process_item(self,item,spider):
        self.exporter.export_item(item)#写入文件
        return item
    def close_spider(self,spider):#实测中发现将close_spider替换成spider_closed也没有问题
        self.exporter.finish_exporting()#结束写入
        self.file.close()

#重构ImagesPipeline，处理图片下载
# class ArticleImagePipeline(ImagesPipeline):
#     #重构item_completed方法
#     def item_completed(self, results, item, info):
#         if "front_image_url" in item:
#             for ok,value in results:
#                 front_image_path=value['path']#获取图片的本地保存路径
#             item['front_image_path']=front_image_path#没有处理前front_image_url的值是一个远程网络地址，具体查看joobbole中的front_image_url
#         return item

#写入数据库，mysql同步操作
# class MysqlPipeline(object):
#     def __init__(self):
#         self.connect=MySQLdb.connect('127.0.0.1','root','root','article_spider',charset="utf8",use_unicode=True)
#         self.cursor=self.connect.cursor()
#     def process_item(self,item,spider):
#         insert_sql="""
#                 insert into jobbole_article(title,url,create_date,fav_nums)
#                 values(%s,%s,%s,%s)
#                 """
#         #mysql写入
#         self.cursor.execute(insert_sql,(item['title'],item['url'],item['create_date'],item['fav_nums']))
#         #mysql关闭
#         self.connect.commit()

#scrapy提供的mysql连接池，异步插入数据库操作
class MysqlTwistedPipline(object):
    def __init__(self,dbpool):
        self.dbpool=dbpool
    @classmethod
    def from_settings(cls,settings):
        dbparams=dict(
            host=settings["MYSQL_HOST"],
            db=settings["MYSQL_DBNAME"],
            user=settings["MYSQL_USER"],
            passwd=settings["MYSQL_PASSWORD"],
            charset="utf8",
            cursorclass=MySQLdb.cursors.DictCursor,#实际测试中删除此项依然能够正常运行
            use_unicode=True
        )
        #生成连接池
        dbpool=adbapi.ConnectionPool("MySQLdb",**dbparams)# MySQLdb数据库模块的名称,dbparams数据库模块参数
        return cls(dbpool)

    def process_item(self, item, spider):
        # 通过连接池执行具体的sql操作，返回一个对象
        query=self.dbpool.runInteraction(self.do_insert,item)
        query.addErrback(self.handel_error,item,spider)#获取异步执行的错误,item、spider参数可以不传，相应的方法中也要取消参数

    #参数item主要是用来跟踪bug的数据源，可以打印出整个数据列表包括出问题的字段值
    #failure是默认参数,item,spider可以不传
    def handel_error(self,failure,item,spider):
        print(failure)

    def do_insert(self,cursor,item):
        #根据不同的item，构建不同的sql语句，并插入到数据库中
        #执行具体的插入数据
        #将下面的代码迁移到item中,这样就不用使用如下代码进行分别判断了
        #if item.__class__.__name__ == "JobBoleArticleItem":
        #   insert_sql = """
        #               insert into jobbole_article(title,create_date,url,url_object_id,front_image_url,front_image_path,comment_nums,fav_nums,praise_nums,tags,content)
        #               values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
        #               """
        #   # mysql写入,如果使用item值则必须在items.py中定义
        #   cursor.execute(insert_sql, (item['title'], item['create_date'], item['url'], item['url_object_id'],item['front_image_url'],item['front_image_path'],item['comment_nums'],item['fav_nums'],item['praise_nums'],item['tags'],item['content']))
        #   对数据库进行插入操作，并不需要commit，twisted会自动帮我commit

        insert_sql,params=item.get_insert_sql()
        cursor.execute(insert_sql,params)
